#include "raft_utils/Config.h"

#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>

#include "bq_common/types/string.h"
#include "bq_log/bq_log.h"
#include "rapidjson/document.h"

raft::utils::Config::Config() : raft_core_(), log_() {
    load_config();
    log_config();

    // 打印一些花里胡哨的logo
    std::cout << R"(                                                                        ,----,                                          
       ,--.                                                           ,/   .`|                   ,-.----.   ,-.----.    
   ,--/  /|                 ,-.----.      ,---,           ,---,.    ,`   .'  :          ,----..  \    /  \  \    /  \   
,---,': / '    ,---.        \    /  \    '  .' \        ,'  .' |  ;    ;     /         /   /   \ |   :    \ |   :    \  
:   : '/ /    /__./|        ;   :    \  /  ;    '.    ,---.'   |.'___,/    ,'         |   :     :|   |  .\ :|   |  .\ : 
|   '   ,,---.;  ; |        |   | .\ : :  :       \   |   |   .'|    :     |          .   |  ;. /.   :  |: |.   :  |: | 
'   |  //___/ \  | |        .   : |: | :  |   /\   \  :   :  :  ;    |.';  ;          .   ; /--` |   |   \ :|   |   \ : 
|   ;  ;\   ;  \ ' |        |   |  \ : |  :  ' ;.   : :   |  |-,`----'  |  |          ;   | ;    |   : .   /|   : .   / 
:   '   \\   \  \: |        |   : .  / |  |  ;/  \   \|   :  ;/|    '   :  ;          |   : |    ;   | |`-' ;   | |`-'  
|   |    ';   \  ' .        ;   | |  \ '  :  | \  \ ,'|   |   .'    |   |  '          .   | '___ |   | ;    |   | ;     
'   : |.  \\   \   '        |   | ;\  \|  |  '  '--'  '   :  '      '   :  |          '   ; : .'|:   ' |    :   ' |     
|   | '_\.' \   `  ;        :   ' | \.'|  :  :        |   |  |      ;   |.'           '   | '/  ::   : :    :   : :     
'   : |      :   \ |        :   : :-'  |  | ,'        |   :  \      '---'             |   :    / |   | :    |   | :     
;   |,'       '---"         |   |.'    `--''          |   | ,'                         \   \ .'  `---'.|    `---'.|     
'---'                       `---'                     `----'                            `---`      `---`      `---`     
                                                                                                                        )"
              << "\n";
}

raft::utils::Config::~Config() {
    // 在退出前强制同步日志
    bq::log::force_flush_all_logs();
    bq::log::uninit();
}

bool raft::utils::Config::determine_log_level(const char *log_level) {
    static std::unordered_map<char, std::string> levelMap = {
            {'v', "verbose,debug,info,warning,error,fatal"},
            {'d', "debug,info,warning,error,fatal"},
            {'i', "info,warning,error,fatal"},
            {'w', "warning,error,fatal"},
            {'e', "error,fatal"},
            {'f', "fatal"}};
    auto it = levelMap.find(log_level[0]);
    if (it != levelMap.end()) {
        log_.log_level = it->second;
        return true;
    }
    return false;
}

bool raft::utils::Config::load_config() {
    std::ifstream file("raft_config.json");
    if (!file.is_open()) {
        std::cerr << "Failed to open configuration file, please check the raft_config.json file.\n";
        exit(-1);
    }

    std::stringstream buffer;
    buffer << file.rdbuf();
    std::string config_str = buffer.str();

    // 解析为json
    rapidjson::Document doc;
    doc.Parse(config_str.c_str());
    if (doc.HasParseError()) {
        std::cerr << "The configuration file is incorrect because it is not in JSON format. Please check the configuration file (applicationconfig. json) information.\n";
        exit(-1);
    }


    /*
     * 日志信息
     */
    if (!doc.HasMember("log")) {
        std::cerr << "The configuration file is incorrect as it does not contain the 'log' option. Please check the configuration file information.\n";
        exit(-1);
    }
    assert(doc["log"].IsObject());
    const rapidjson::Value &log_object = doc["log"];
    // 日志文件名
    assert(log_object["log_name"].GetString());
    log_.log_name = log_object["log_name"].GetString();

    // 日志等级
    assert(log_object["log_level"].GetString());
    if (!determine_log_level(log_object["log_level"].GetString())) {
        std::cerr << "The configuration file is incorrect because the 'log_level' option is filled in incorrectly. Please check the configuration file information.\n";
        exit(-1);
    }


    /*
     * state_machine 模块
     */
    if (!doc.HasMember("state_machine")) {
        std::cerr << "The configuration file is incorrect as it does not contain the 'state_machine' option. Please check the configuration file information.\n";
        exit(-1);
    }
    assert(doc["state_machine"].IsObject());
    const rapidjson::Value &state_machine_object = doc["state_machine"];
    // 状态机监听的 ip
    assert(state_machine_object["ip"].GetString());
    state_machine_.ip = state_machine_object["ip"].GetString();

    // 状态机监听的端口
    assert(state_machine_object["port"].GetInt());
    state_machine_.port = state_machine_object["port"].GetInt();


    /*
     * raft_core 模块
     */
    if (!doc.HasMember("raft_core")) {
        std::cerr << "The configuration file is incorrect as it does not contain the 'raft_core' option. Please check the configuration file information.\n";
        exit(-1);
    }
    assert(doc["raft_core"].IsObject());
    const rapidjson::Value &raft_core_object = doc["raft_core"];
    // 乘数因子
    assert(raft_core_object["multiplier_factor"].GetInt());
    raft_core_.multiplier_factor = raft_core_object["multiplier_factor"].GetInt();

    // 心跳超时时间
    assert(raft_core_object["heart_beat_timeout"].GetInt());
    raft_core_.heart_beat_timeout = raft_core_object["heart_beat_timeout"].GetInt() * raft_core_.multiplier_factor;

    // 应用日志条目的间隔时间
    assert(raft_core_object["apply_interval"].GetInt());
    raft_core_.apply_interval = raft_core_object["apply_interval"].GetInt() * raft_core_.multiplier_factor;

    // 选举超时的最小值
    assert(raft_core_object["min_randomized_vote_time"].GetInt());
    raft_core_.min_randomized_vote_time = raft_core_object["min_randomized_vote_time"].GetInt() * raft_core_.multiplier_factor;

    // 选举超时最大值
    assert(raft_core_object["max_randomized_vote_time"].GetInt());
    raft_core_.max_randomized_vote_time = raft_core_object["max_randomized_vote_time"].GetInt() * raft_core_.multiplier_factor;

    // 达成共识的超时时间
    assert(raft_core_object["consensus_timeout"].GetInt());
    raft_core_.consensus_timeout = raft_core_object["consensus_timeout"].GetInt() * raft_core_.multiplier_factor;

    // 节点最大数据值
    assert(raft_core_object["max_raft_state"].GetInt());
    raft_core_.max_raft_state = raft_core_object["max_raft_state"].GetInt();

    // 当前节点的 IP
    assert(raft_core_object["ip"].IsString());
    raft_core_.ip = raft_core_object["ip"].GetString();

    // 当前节点端口
    assert(raft_core_object["port"].IsInt());
    raft_core_.port = raft_core_object["port"].GetInt();

    // 其他节点 (peers)
    assert(raft_core_object["peers"].IsArray());
    const rapidjson::Value &peers_array = raft_core_object["peers"];
    for (rapidjson::SizeType i = 0; i < peers_array.Size(); i++) {
        const rapidjson::Value &peer = peers_array[i];
        assert(peer.IsObject());
        assert(peer["ip"].IsString());
        assert(peer["port"].IsInt());

        std::string peer_ip = peer["ip"].GetString();
        int peer_port = peer["port"].GetInt();
        raft_core_.peers.emplace_back(peer_ip, peer_port);
    }

    return true;
}


void raft::utils::Config::log_config() const {
    bq::string config = R"(
        #第一个Appender名叫appender_0，他的类型是ConsoleAppender
        appenders_config.appender_0.type=console
        #appender_0对应的时区是系统当地时间
        appenders_config.appender_0.time_zone=default local time
        #appender_0会输出所有6个等级的日志（注意，每个日志等级之间千万不要有空格，不然会解析失败）
        appenders_config.appender_0.levels=[)";
    config += log_.log_level;
    config += R"(]
                
        #第二个Appender名叫appender_2，他的类型是CompressedFileAppender
        appenders_config.appender_2.type=compressed_file
        #appender_2会输出所有等级的日志
        appenders_config.appender_2.levels=[debug,info,warning,error,fatal]
        #appender_2保存的路径会是在程序的相对路径bqLog目录下，文件名用compress_log开头，后面会跟上日期和.logcompr扩展名
        appenders_config.appender_2.file_name=bqLog/compress_log
            

        #总的异步缓存的buffer size为65535字节，具体意义看后文详细解释
        log.buffer_size=65535
        #日志的可靠等级为normal，具体意义看后文详细解释
        log.reliable_level=normal
        #只有当日志的category符合下面这三种通配符的时候，才会被处理，否则全部忽略，具体见后文详细解释（Category的概念会在后面的高级使用话题）
        log.categories_mask=[*default,ModuleA,ModuleB.SystemC]
        #这是一个异步日志，异步日志是性能最高的日志，也是推荐的日志类型
        log.thread_mode=async
        #如果日志等级是error和fatal的话，在每一条日志后面带上调用栈信息
        log.print_stack_levels=[error,fatal]

        #启用快照功能，快照缓存64K
        snapshot.buffer_size=65536
        #只有info和error等级的日志才会被快照记录
        snapshot.levels=[info,error]
        #只有当日志的category是ModuleA,ModuleB.SystemC开头的时候，才会被快照记录，否则全部忽略
        snapshot.categories_mask=[ModuleA.SystemA.ClassA,ModuleB]
    )";

    static bq::log log = bq::log::create_log(log_.log_name, config);
    log.debug("Log initialization successful");
}


std::string raft::utils::Config::get_log_name() const {
    return log_.log_name;
}

std::string raft::utils::Config::get_state_machine_rpc_ip() const {
    return state_machine_.ip;
}

int raft::utils::Config::get_state_machine_rpc_port() const {
    return state_machine_.port;
}

int raft::utils::Config::get_heart_beat_timeout() const {
    return raft_core_.heart_beat_timeout;
}

int raft::utils::Config::get_apply_interval() const {
    return raft_core_.apply_interval;
}

int raft::utils::Config::get_min_randomized_vote_time() const {
    return raft_core_.min_randomized_vote_time;
}

int raft::utils::Config::get_max_randomized_vote_time() const {
    return raft_core_.max_randomized_vote_time;
}

int raft::utils::Config::get_consensus_timeout() const {
    return raft_core_.consensus_timeout;
}

int raft::utils::Config::get_max_raft_state() const {
    return raft_core_.max_raft_state;
}

std::string raft::utils::Config::get_raft_core_ip() const {
    return raft_core_.ip;
}

int raft::utils::Config::get_raft_core_port() const {
    return raft_core_.port;
}

std::vector<std::pair<std::string, int>> raft::utils::Config::get_raft_core_peer() const {
    return raft_core_.peers;
}
